#include "CUnit.h"
#include "SGD Wrappers/CSGD_Direct3D.h"
#include "SGD Wrappers/CSGD_TextureManager.h"
#include "CObjectManager.h"
#include "SGD Wrappers/CSGD_DirectInput.h"
#include "CGamePlayState.h"
#include "CAnimationManager.h"
#include "CGame.h"
#include "CHealthBar.h"
#include "CInterestBar.h"
#include "CEventSystem.h"
#include "Mail System.h"
#include "CEmitter.h"
#include "CWorldCollision.h"
#include "SGD Wrappers/CSGD_FModManager.h"

#define	 RANDOM_FLOAT(min,max) (((rand()/(float)RAND_MAX)*((max)-(min)))+(min))
#define		XMIN	0
#define		XMAX	800
#define		YMIN	0
#define		YMAX	600

CUnit::CUnit()
{
	CEventSystem::GetInstance()->RegisterClient("UNIT_HEAL", this);
	m_nType = UNIT;
	m_fNoteTime = 0;
	m_nUnitType = BASE_UNIT;
	travelingVec.fX = 0;
	travelingVec.fY = -1;
	targetVec.fX = 0;
	targetVec.fY = -1;
	//DeathLevel(NULL);
	SetPower(0);
	SetRange(0);
	SetMaxHP(0);
	SetCurrHP(0);
	SetCost(0);
	MaxInterest(0);
	CurrInterest(0);
	m_fTimeElapsed = 0;
	m_pPlayer = CPlayer::GetInstance();

	m_pUnit.nCurrAnimation = RAT_SIDE;
	m_pUnit.nCurrFrame = 0;
	m_pUnit.nTimer = 0;
	m_bIsFlipped = false;
	m_bIsDead = false;
	pEmitter = NULL;

	m_nRatHappy = CSGD_FModManager::GetInstance()->LoadSound("resource/sound/Rat_Squeaks.wav");
	m_nChildHappy = CSGD_FModManager::GetInstance()->LoadSound("resource/sound/Child_Laughing.wav");
}
CUnit::~CUnit()
{
	CEventSystem::GetInstance()->UnregisterClient("UNIT_HEAL", this);
	if(pEmitter != NULL)
	{
		CParticleManager::GetInstance()->RemoveEmitter(pEmitter);
		pEmitter = NULL;
	}
}
void CUnit::Init(
				 float fPosX, float fPosY, float fVelX, float fVelY, int nMaxHP, 
				 int nCurHP, int nHeight, int nWidth, int nSpeed, int State, CHero* pHero)
{
	SetPosX(fPosX);
	SetPosY(fPosY);
	SetVelX(fVelX);
	SetVelY(fVelY);
	SetMaxHP(nMaxHP);
	SetCurrHP(nCurHP);
	SetHeight(nHeight);
	SetWidth(nWidth);
	SetSpeed((float)nSpeed);
	m_nState = State;
}
void CUnit::Update(float fDelta)
{
	if(m_fCurrInterest > 100)
		m_fCurrInterest = 100;
	else if(m_fCurrInterest < 0)
		m_fCurrInterest = 0;
	float posX = (GetPosX() + GetWidth()/2);
	float posY = (GetPosY() + GetHeight()/2);

		CBase::Update(fDelta);
		if(GetPosX() <= XMIN)
			SetPosX(XMIN);
		else if(GetPosX() >= XMAX)
			SetPosX(XMAX);
		else if(GetPosY() <= YMIN)
			SetPosY(YMIN);
		else if(GetPosY() >= YMAX)
			SetPosY(YMAX);

		m_fTimeElapsed += fDelta;

	if(!m_bIsDead)
	{
		if(m_NotePattern.Listen())
		{
			float heroX = (m_pPlayer->GetPosX() + m_pPlayer->GetWidth()/2);
			float heroY = (m_pPlayer->GetPosY() + m_pPlayer->GetHeight()/2);
			toPlayer.fX = heroX - posX;
			toPlayer.fY = heroY - posY;
			Vector2DNormalize(toPlayer);
			if((Vector2DLength(toPlayer) <= 75 || State() == FOLLOWING_PLAYER) && m_fCurrInterest < 100)
			{
				m_fCurrInterest += 80;
				m_NotePattern.Init();
				m_fNoteTime = 0;
			}
		}
		if(m_fCurrInterest >= 50)
		{
			if(m_nState != FOLLOWING_PLAYER)
			{
				if(UnitType() == CHILD)
				{
					if(!CSGD_FModManager::GetInstance()->IsSoundPlaying(m_nChildHappy))
						CSGD_FModManager::GetInstance()->PlaySound(m_nChildHappy);
					CSGD_FModManager::GetInstance()->SetVolume(m_nChildHappy, CGame::GetInstance()->SFXVol());

				}
				else
				{
					if(!CSGD_FModManager::GetInstance()->IsSoundPlaying(m_nRatHappy))
						CSGD_FModManager::GetInstance()->PlaySound(m_nRatHappy);
					CSGD_FModManager::GetInstance()->SetVolume(m_nChildHappy, CGame::GetInstance()->SFXVol());
				}
				m_nState = FOLLOWING_PLAYER;
			}
			if(pEmitter == NULL)
			{
				pEmitter = CParticleManager::GetInstance()->AddEmitter((int)GetPosX(), (int)GetPosY(), "Resource/Particle Effects/selected.rpe");
				pEmitter->PlayEffect(true);
				/*HasEmitter = true;*/
			}
		}
		if(m_fCurrInterest < 50)
		{
			if(m_nState != WANDERING)
			{
				m_nState= WANDERING;
				startX = GetPosX();
				startY = GetPosY();
				nextSpotX = RANDOM_FLOAT(startX - 50, startX + 50);
				nextSpotY = RANDOM_FLOAT(startY - 50, startY + 50);
				for(;;)
				{
					bool one = false;
					bool two = false;
					if(nextSpotX >= XMAX || nextSpotX <= XMIN)
						nextSpotX = RANDOM_FLOAT(startX - 50, startX + 50);
					else
						one = true;
					if(nextSpotY >= YMAX || nextSpotY <= YMIN)
						nextSpotY = RANDOM_FLOAT(startY - 50, startY + 50);
					else
						two = true;
					if(one && two)
						break;
				}
			}
			if(pEmitter != NULL)
			{
				pEmitter->PlayEffect(false);
				CParticleManager::GetInstance()->RemoveEmitter(pEmitter);
				pEmitter = NULL;
			}
		}

		if(m_fCurrInterest > 0 && (m_pPlayer->GetIsRunning() == true || Vector2DLength(toPlayer) > 75))
			m_fCurrInterest -= fDelta*5;
		else
			m_fCurrInterest -= fDelta;

		if(GetVelX() != 0 || GetVelY() != 0)
			CAnimationManager::GetInstance()->Update(fDelta, &m_pUnit);
		else
			m_pUnit.nCurrFrame = 0;

		if(m_nState == WANDERING)
		{
			travelingVec.fX = nextSpotX - posX;
			travelingVec.fY = nextSpotY - posY;
			Vector2DNormalize(travelingVec);

			if(Vector2DLength(travelingVec) > 1)
			{
				SetVelX(travelingVec.fX * fDelta);
				SetVelY(travelingVec.fY * fDelta);
				SetPosX(GetPosX() + GetVelX());
				SetPosY(GetPosY() + GetVelY());
			}
			else
			{
				nextSpotX = RANDOM_FLOAT(startX - 50, startX + 50);
				nextSpotY = RANDOM_FLOAT(startY - 50, startY + 50);
			}
		}
		if(m_nState == FOLLOWING_PLAYER)
		{
			float heroX = (m_pPlayer->GetPosX() + m_pPlayer->GetWidth()/2);
			float heroY = (m_pPlayer->GetPosY() + m_pPlayer->GetHeight()/2);
			travelingVec.fX = heroX - posX;
			travelingVec.fY = heroY - posY;
			Vector2DNormalize(travelingVec);
			if(Vector2DLength(travelingVec) >= 75)
			{
				SetVelX(travelingVec.fX * fDelta);
				SetVelY(travelingVec.fY * fDelta);
				float x = GetVelX();
				float y = GetVelY();
				SetPosX(GetPosX() + GetVelX());
				SetPosY(GetPosY() + GetVelY());

			}
			else if(Vector2DLength(travelingVec) <= 60)
			{
				SetVelX(-travelingVec.fX * fDelta);
				SetVelY(-travelingVec.fY * fDelta);
				float x = GetVelX();
				float y = GetVelY();
				SetPosX(GetPosX() + GetVelX());
				SetPosY(GetPosY() + GetVelY());
			}
		}
		if(pEmitter != NULL)
		{
			pEmitter->SetPosX(GetPosX());
			pEmitter->SetPosY(GetPosY());
		}

	}

	if(UnitType() == CHILD)
	{
		if(m_bIsDead)
		{
			if(m_pUnit.nCurrAnimation != BOY_DEAD)
				m_pUnit.ChangeAnimation(BOY_DEAD);
		}
		else
		{
			if(GetVelY() < -1)
			{
				if(m_pUnit.nCurrAnimation != BOY_SIDE)
					m_pUnit.ChangeAnimation(BOY_SIDE);
				m_bIsFlipped = false;
			}
			else if(GetVelX() > 1)
			{
				if(m_pUnit.nCurrAnimation != BOY_SIDE)
					m_pUnit.ChangeAnimation(BOY_SIDE);
				m_bIsFlipped = true;
			}

			if (GetVelY() < -1)
			{
				if(m_pUnit.nCurrAnimation != BOY_UP)
					m_pUnit.ChangeAnimation(BOY_UP);
				m_bIsFlipped = false;
			}
			if (GetVelY() > 1)
			{
				if(m_pUnit.nCurrAnimation != BOY_DOWN)
					m_pUnit.ChangeAnimation(BOY_DOWN);
				m_bIsFlipped = false;
			}
		}
	}

	if(UnitType() == RAT || UnitType() == MENURAT)
	{
		if(m_bIsDead)
		{
			if(m_pUnit.nCurrAnimation != RAT_DEAD)
				m_pUnit.ChangeAnimation(RAT_DEAD);
		}
		else
		{
			if(GetVelX() < -1)
			{
				if(m_pUnit.nCurrAnimation != RAT_SIDE)
					m_pUnit.ChangeAnimation(RAT_SIDE);
				m_bIsFlipped = false;
			}
			if(GetVelX() > 1)
			{
				if(m_pUnit.nCurrAnimation != RAT_SIDE)
					m_pUnit.ChangeAnimation(RAT_SIDE);
				m_bIsFlipped = true;
			}

			if (GetVelY() < -1)
			{
				if(m_pUnit.nCurrAnimation != RAT_UP)
					m_pUnit.ChangeAnimation(RAT_UP);
				m_bIsFlipped = false;
			}
			if (GetVelY() > 1)
			{
				if(m_pUnit.nCurrAnimation != RAT_DOWN)
					m_pUnit.ChangeAnimation(RAT_DOWN);
				m_bIsFlipped = false;
			}
		}

	}
	m_fNoteTime += fDelta;
	if(m_fNoteTime >= 30)
	{
		m_fNoteTime = 0;
		m_NotePattern.Init();
	}

	if(m_bIsDead && DeathLevel() == CLIFF)
	{
		SetVelY(100);

		if(GetPosY() > CGame::GetInstance()->GetScreenHeight() - GetHeight())
		{
			MailSystem::GetInstance()->SendMail(new DeleteUnitMessage(this));
		}
	}
}
void CUnit::Render()
{
	////////////////////////////////////////////////////
	//	Render Collision Box
	CSGD_Direct3D::GetInstance()->SpriteEnd();

	//CSGD_Direct3D::GetInstance()->DrawRect(GetDrawRect(), 0,255,0);

	CSGD_Direct3D::GetInstance()->SpriteBegin();
	if(!m_bIsDead)
	{
		CAnimationManager::GetInstance()->Render((int)(
			GetPosX() - GetHalfWidth()), 
			(int)(GetPosY() - GetHalfHeight()), 
			1, -1, m_pUnit, m_bIsFlipped);
	}
	else if(m_bIsDead && DeathLevel() == CGamePlayState::GetInstance()->CurrLevel()->GetCurrArea())
	{
		CAnimationManager::GetInstance()->Render((int)(
			GetPosX() - GetHalfWidth()), 
			(int)(GetPosY() - GetHalfHeight()), 
			1, -1, m_pUnit, m_bIsFlipped);
	}

	//	Render Health Bar
	if(UnitType() != MENURAT && !m_bIsDead)
	{
		CHealthBar::GetInstance()->Render(this);
		CInterestBar::GetInstance()->Render(this);

		//	Render Interest Notes
		m_NotePattern.Render(GetPosX()-10, GetPosY()-10);
		//
		////////////////////////////////////////////////////
	}
}
bool CUnit::Collision(CBase *pBase)
{
	if(m_bIsDead)
	{
		return false;
	}
	if(CBase::Collision(pBase) && pBase != this)
	{
		if(pBase->GetType() == UNIT)
		{
			if(((CUnit*)pBase)->IsDead())
			{
				return false;
			}
			CWorldCollision::GetInstance()->CollideWithTile(this, (CLevelCollision*)pBase);
			return true;
		}
		else if(pBase->GetType() == HERO)
		{
			CWorldCollision::GetInstance()->CollideWithTile(this, (CLevelCollision*)pBase);
			return true;
		}
		else if(pBase->GetType() == LEVEL_COLLISION)
		{
			CLevelCollision* temp = (CLevelCollision*)pBase;
			if(temp->CollisionType() == NORMAL_COLLISION)
				CWorldCollision::GetInstance()->CollideWithTile(this, (CLevelCollision*)pBase);
			else
				Damage(5);
			return true;
		}
		else
			return false;
	}	
	else
		return false;
}

void CUnit::HandleEvent(CEvent* pEvent)
{
	//if(pEvent->GetEventID() == "UNIT_HEAL" && pEvent->GetParam() == m_pHero)
	//{
	//	float posX = GetPosX();
	//	float posY = GetPosY();

	//	tVector2D travelingVec;
	//	travelingVec.fX = 0;
	//	travelingVec.fY = -1;

	//	travelingVec.fX = (m_pHero->GetPosX() + m_pHero->GetHalfWidth()) - posX;
	//	travelingVec.fY = (m_pHero->GetPosY() + m_pHero->GetHalfHeight()) - posY;

	//	float temp = Vector2DLength(travelingVec);
	//	if( temp <= 100)
	//	{
	//		SetCurrHP(GetCurrHP() + 5);
	//		if(GetCurrHP() >= GetMaxHP())
	//			SetCurrHP(GetMaxHP() - 1);
	//	}
	//}
}

void CUnit::Damage(int nDamage)
{
	SetCurrHP(GetCurrHP() - nDamage);
	if(GetCurrHP() <= 0)
	{
		MailSystem::GetInstance()->SendMail(new DestroyUnitMessage(this));
		if(pEmitter != NULL)
		{
			CParticleManager::GetInstance()->RemoveEmitter(pEmitter);
			pEmitter = NULL;
		}
	}
}